﻿//----------------------------------------------------------------
// Desc: 
// Edit: ShowLong, http://blog.csdn.net/showlong
//
// Date Created: 2012-12-26
//
// Update Date : 
//
// Copyright (c) Fuel Game Engine (http://www.fge-engine.com), All rights reserved.
//
//----------------------------------------------------------------
#pragma once


class IFActionObject;
class IFActionSystem;


#pragma pack(push, 1)


//----------------------------------------------------------------
// 行为系统常量
//----------------------------------------------------------------
enum EF_ACTION_SYS_DEFINE
{
    eASD_MaxParamater           = 9,    // 最大支持9个参数
    eASD_InvalidASNode          = 0,    // 无效行为栈节点
};


//----------------------------------------------------------------
// 启动此行为时的执行模式，瞬间执行类型行，这些模式没用
//----------------------------------------------------------------
enum EF_ACTION_SYS_MODE
{
    eASM_Replace,                       // 替换，顶掉上一个行为
    eASM_Interrupt,                     // 中断当前行为，完成以后自动恢复中断前的行为
    eASM_Parallel,                      // 与上一个行为并行处理
};


//----------------------------------------------------------------
// 其它标记组合
//----------------------------------------------------------------
enum EF_ACTION_SYS_FLAGS
{
    eASF_NoFlags                = 0,
    eASF_Endless                = 1<<0, // 行为的运行时间是无限循环，直到中断、顶替、强制结束等
    eASF_NonIndependent         = 1<<1, // 非独立行为（当并行的行为表中其它独立行为结束时，且剩下的是此标记行为，那么此行为也结束）
    eASF_Suspend                = 1<<2, // 行为挂起中
    eASF_Monopolize             = 1<<3, // 独占模式（当行为有时长时，任何需要执行的新行为都将失败，仅能强制结束或者运行结束。且和它一起并行的行为也被附加独占能力，直到此独占行为结束以后才恢复正常）
    eASF_IgnoreMonopolize       = 1<<4, // 忽略独占，仅在启动行为时有用（如果当前行为是独占的，那么忽略掉它，强制执行此行为）
};


//----------------------------------------------------------------
// AI条件判断方法
//----------------------------------------------------------------
enum EF_ACTION_SYS_AI_COMPARE
{
    eASAC_Equal,                        // 相等
    eASAC_UnEqual,                      // 不相等
    eASAC_Greater,                      // 大于
    eASAC_GreaterEqual,                 // 大于等于
    eASAC_Less,                         // 小于
    eASAC_LessEqual,                    // 小于等于
};


//----------------------------------------------------------------
// 行为的执行时机
//----------------------------------------------------------------
enum EF_ACTION_SYS_AI_EXECUTE
{
    eASAE_Enter,                        // 进入状态时执行（如果有条件，则直到条件满足时才执行，仅此一次）
    eASAE_Run,                          // 运行过程中按条件执行（只要条件满足就执行，每帧都会判断）
    eASAE_Leave,                        // 离开状态时执行（此时机的延时处理无效，只要条件满足，将被改为立即执行）
};


//----------------------------------------------------------------
// AI状态
//----------------------------------------------------------------
enum EF_ACTION_SYS_AI_STATE
{
    eASAS_Executed              = 1<<0, // 已执行（eASAE_Enter时机类型时有效）

    eASAS_Default = 0,                  // 默认状态
};


//----------------------------------------------------------------
// 行为参数列表
//----------------------------------------------------------------
struct FActionParameter
{
    FDECLARE_STRUCT(FActionParameter)

    FDT_VALUE _vpdt[eASD_MaxParamater]; // 参数列表（类型及默认值）

    FINLINE FActionParameter()
    {}
    FINLINE FActionParameter(FDT_VALUE p1)
    {
        _vpdt[0].t = p1.t, _vpdt[0].v = p1.v;
    }
    FINLINE FActionParameter(FDT_VALUE p1, FDT_VALUE p2)
    {
        _vpdt[0].t = p1.t, _vpdt[0].v = p1.v;
        _vpdt[1].t = p2.t, _vpdt[1].v = p2.v;
    }
    FINLINE FActionParameter(FDT_VALUE p1, FDT_VALUE p2, FDT_VALUE p3)
    {
        _vpdt[0].t = p1.t, _vpdt[0].v = p1.v;
        _vpdt[1].t = p2.t, _vpdt[1].v = p2.v;
        _vpdt[2].t = p3.t, _vpdt[2].v = p3.v;
    }
    FINLINE FActionParameter(FDT_VALUE p1, FDT_VALUE p2, FDT_VALUE p3, FDT_VALUE p4)
    {
        _vpdt[0].t = p1.t, _vpdt[0].v = p1.v;
        _vpdt[1].t = p2.t, _vpdt[1].v = p2.v;
        _vpdt[2].t = p3.t, _vpdt[2].v = p3.v;
        _vpdt[3].t = p4.t, _vpdt[3].v = p4.v;
    }
    FINLINE FActionParameter(FDT_VALUE p1, FDT_VALUE p2, FDT_VALUE p3, FDT_VALUE p4, FDT_VALUE p5)
    {
        _vpdt[0].t = p1.t, _vpdt[0].v = p1.v;
        _vpdt[1].t = p2.t, _vpdt[1].v = p2.v;
        _vpdt[2].t = p3.t, _vpdt[2].v = p3.v;
        _vpdt[3].t = p4.t, _vpdt[3].v = p4.v;
        _vpdt[4].t = p5.t, _vpdt[4].v = p5.v;
    }
    FINLINE FActionParameter(FDT_VALUE p1, FDT_VALUE p2, FDT_VALUE p3, FDT_VALUE p4, FDT_VALUE p5, FDT_VALUE p6)
    {
        _vpdt[0].t = p1.t, _vpdt[0].v = p1.v;
        _vpdt[1].t = p2.t, _vpdt[1].v = p2.v;
        _vpdt[2].t = p3.t, _vpdt[2].v = p3.v;
        _vpdt[3].t = p4.t, _vpdt[3].v = p4.v;
        _vpdt[4].t = p5.t, _vpdt[4].v = p5.v;
        _vpdt[5].t = p6.t, _vpdt[5].v = p6.v;
    }
    FINLINE FActionParameter(FDT_VALUE p1, FDT_VALUE p2, FDT_VALUE p3, FDT_VALUE p4, FDT_VALUE p5, FDT_VALUE p6, FDT_VALUE p7)
    {
        _vpdt[0].t = p1.t, _vpdt[0].v = p1.v;
        _vpdt[1].t = p2.t, _vpdt[1].v = p2.v;
        _vpdt[2].t = p3.t, _vpdt[2].v = p3.v;
        _vpdt[3].t = p4.t, _vpdt[3].v = p4.v;
        _vpdt[4].t = p5.t, _vpdt[4].v = p5.v;
        _vpdt[5].t = p6.t, _vpdt[5].v = p6.v;
        _vpdt[6].t = p7.t, _vpdt[6].v = p7.v;
    }
    FINLINE FActionParameter(FDT_VALUE p1, FDT_VALUE p2, FDT_VALUE p3, FDT_VALUE p4, FDT_VALUE p5, FDT_VALUE p6, FDT_VALUE p7, FDT_VALUE p8)
    {
        _vpdt[0].t = p1.t, _vpdt[0].v = p1.v;
        _vpdt[1].t = p2.t, _vpdt[1].v = p2.v;
        _vpdt[2].t = p3.t, _vpdt[2].v = p3.v;
        _vpdt[3].t = p4.t, _vpdt[3].v = p4.v;
        _vpdt[4].t = p5.t, _vpdt[4].v = p5.v;
        _vpdt[5].t = p6.t, _vpdt[5].v = p6.v;
        _vpdt[6].t = p7.t, _vpdt[6].v = p7.v;
        _vpdt[7].t = p8.t, _vpdt[7].v = p8.v;
    }
    FINLINE FActionParameter(FDT_VALUE p1, FDT_VALUE p2, FDT_VALUE p3, FDT_VALUE p4, FDT_VALUE p5, FDT_VALUE p6, FDT_VALUE p7, FDT_VALUE p8, FDT_VALUE p9)
    {
        _vpdt[0].t = p1.t, _vpdt[0].v = p1.v;
        _vpdt[1].t = p2.t, _vpdt[1].v = p2.v;
        _vpdt[2].t = p3.t, _vpdt[2].v = p3.v;
        _vpdt[3].t = p4.t, _vpdt[3].v = p4.v;
        _vpdt[4].t = p5.t, _vpdt[4].v = p5.v;
        _vpdt[5].t = p6.t, _vpdt[5].v = p6.v;
        _vpdt[6].t = p7.t, _vpdt[6].v = p7.v;
        _vpdt[7].t = p8.t, _vpdt[7].v = p8.v;
        _vpdt[8].t = p9.t, _vpdt[8].v = p9.v;
    }
    FINLINE FDT_VALUE& operator [](const int idx)
    {
        FASSERT(idx >= 0 && idx < eASD_MaxParamater, FAssertFmt(_T("行为系统参数列表只支持%d个参数"), eASD_MaxParamater));
        return _vpdt[idx];
    }
    FINLINE operator FActionParameter* ()
    {
        return this;
    }
    FINLINE void Copy(FActionParameter& b)
    {
        FMemcpy(this, &b, sizeof(*this));
    }
};


//----------------------------------------------------------------
// 行为属性
//----------------------------------------------------------------
struct FActionProperty
{
    FDECLARE_STRUCT(FActionProperty)

    BYTE nMode;                         // 模式，EF_ACTION_SYS_MODE
    DWORD nFlags;                       // 标记组合码，EF_ACTION_SYS_FLAGS

    FINLINE FActionProperty(EF_ACTION_SYS_MODE md = eASM_Replace, DWORD flag = eASF_NoFlags)
        :nMode((BYTE)md)
        ,nFlags(flag)
    {}
    FINLINE operator FActionProperty* ()
    {
        return this;
    }
    FINLINE DWORD GetFlag(EF_ACTION_SYS_FLAGS prop)
    {
        return nFlags;
    }
    FINLINE void AddFlag(EF_ACTION_SYS_FLAGS prop)
    {
        nFlags |= prop;
    }
    FINLINE void SubFlag(EF_ACTION_SYS_FLAGS prop)
    {
        nFlags &= ~prop;
    }
    FINLINE bool HasFlag(EF_ACTION_SYS_FLAGS prop)
    {
        return (nFlags & prop) != 0;
    }
    FINLINE void SetFlag(EF_ACTION_SYS_FLAGS prop, bool vl)
    {
        if (vl)
            AddFlag(prop);
        else
            SubFlag(prop);
    }
    FINLINE void SetFlag(EF_ACTION_SYS_FLAGS prop)
    {
        nFlags = prop;
    }
};


//----------------------------------------------------------------
// 行为逻辑处理句柄
//----------------------------------------------------------------
class IFActionHandle : public IFMemObject
{
    friend class IFActionObject;

public:
    const DWORD nTypeID;                // 行为ID
    IFActionObject* pao;                // 所属对象（由行为系统自动填写）
    FActionProperty arp;                // 行为属性
    FActionParameter arg;               // 行为调用参数

    // 构造ID、默认参数列表、默认条件数据
    FINLINE IFActionHandle(DWORD id, FActionParameter* ap = 0, FActionProperty* pt = 0)
        :nTypeID(id)
        ,pao(0)
    {
        if (ap) arg.Copy(*ap);
        if (pt) arp = *pt;
    }
    // 执行此行为，返回是否执行成功
    virtual bool Execute(DWORD nt){ return true; }
    // 运行此行为（有时长的行为才会到这里来），返回是否继续运行此行为行为
    virtual bool Run(DWORD nt, DWORD key){ return true; }
    // 当此行为被中断的时候调用
    virtual void Interrupt(DWORD nt){}
    // 当此行为被恢复的时候调用
    virtual void Recovery(DWORD nt){}

    // 获取此行为的描述信息（当然并一定是此结构，可以自定义）
    struct DESC_INFO
    {
        const ACHAR* name;              // 行为名
        const ACHAR* desc;              // 行为描述
        DESC_INFO()
            :name(_FNILA)
            ,desc(_FNILA)
        {}
    };
    virtual void GetDesc(DESC_INFO* desc){}
};
typedef FVector< IFActionHandle* > fv_as_phandle;


//----------------------------------------------------------------
// 行为通知对象与接口
//----------------------------------------------------------------
class IFActionNotify : public IFMemObject
{
public:
    // 测试是否能从cur切换到dst行为
    // .cur 当前行为队例中的行为，修改里面数据时请注意安全，防止死循环行为或者意外处理结果
    // .dst 保存有调用前传入的数据，且可以修改dst中的参数
    // return 返回是否能切换
    virtual bool CanEnterAction(IFActionHandle* dst){ return true; }
    virtual void EnterAction(IFActionHandle* dst){}
    virtual void LeaveAction(IFActionHandle* dst){}
};


//----------------------------------------------------------------
// 行为堆栈的一个节点
//----------------------------------------------------------------
struct FActionNode
{
    FDECLARE_STRUCT(FActionNode)

    DWORD key;                          // 节点KEY值，等于eASD_InvalidASNode表示无效节点（可用于查找行为）
    fv_as_phandle vah;                  // 节点的行为句柄列表，为空也表示无效节点

    FINLINE FActionNode()
        :key(eASD_InvalidASNode)
    {}
    FINLINE bool IsMonopolize()
    {
        if (key == eASD_InvalidASNode)
            return false;
        for (size_t i = 0; i < vah.size(); ++i)
        {
            if (vah[i]->arp.HasFlag(eASF_Monopolize))
                return true;
        }
        return false;
    }
    FINLINE bool HasAction(DWORD id)
    {
        if (key == eASD_InvalidASNode)
            return false;
        for (size_t i = 0; i < vah.size(); ++i)
        {
            if (vah[i]->nTypeID == id)
                return true;
        }
        return false;
    }
};


//----------------------------------------------------------------
// 行为活体对象及行为执行堆栈信息
//----------------------------------------------------------------
class IFActionObject : public IFMemObject
{
    friend class IFActionSystem;

public:
    IFActionNotify* pNotify;            // 对象接口

protected:
    FINLINE IFActionObject(IFActionNotify* an)
        :pNotify(an)
    {}

public:
    // 取得所在行为系统
    virtual IFActionSystem* GetAS() = 0;
    // 取得当前对象的正在执行的行为，即栈项（如果返回的表是空的，则表示没有行为在执行了）
    virtual FActionNode& GetTopAction() = 0;
    // 取得当前栈向低部走的下一个栈节点
    virtual FActionNode& GetNxtAction(FActionNode& cur) = 0;
    // 取得指定行为栈节点
    virtual FActionNode& FindAction(DWORD key) = 0;
    // 清掉所有行为
    virtual void ClearAction() = 0;

    // 取得对象接口
    template < typename _Ty >
    FINLINE _Ty* GetNotify(){ return (_Ty*)pNotify; }
};
typedef FVector< IFActionObject* > fv_as_pobject;


//----------------------------------------------------------------
// AI条件
//----------------------------------------------------------------
class IFAIObject;
class IFAICondition : public IFMemObject
{
public:
    const DWORD nTypeID;                // 条件ID
    IFAIObject* pAO;                    // 绑定的AI对象

    IFAICondition(DWORD id)
        :nTypeID(id)
        ,pAO(0)
    {}

    // 查询当前的条件结果（true=1,false=0,其它按值返回）
    virtual int Query(){ return 0; }

    // 获取此条件的描述信息（当然并一定是此结构，可以自定义）
    struct DESC_INFO
    {
        const ACHAR* name;              // 条件名
        DESC_INFO()
            :name(_FNILA)
        {}
    };
    virtual void GetDesc(DESC_INFO* desc){}
};
typedef FVector< IFAICondition* > fv_as_ai_pcondition;


//----------------------------------------------------------------
// AI执行命令
//----------------------------------------------------------------
class IFAICommand : public IFMemObject
{
public:
    DWORD id;                           // 需要执行行为ID
    FActionParameter arg;               // 执行行为时的参数
    FActionProperty arp;                // 执行行为时的属性
    DWORD delay_t;                      // 延迟时间
    DWORD freq_min_t, freq_max_t;       // 重复执行时的随机频率区间（仅在eASAE_Run模式下有效）

    FINLINE IFAICommand(DWORD id, DWORD det = 0, FActionParameter* ap = 0, FActionProperty* pt = 0)
        :id(id)
        ,delay_t(det)
        ,freq_min_t(0)
        ,freq_max_t(0)
    {
        if (ap) arg.Copy(*ap);
        if (pt) arp = *pt;
    }
    // 添加条件（重复的条件自动抛弃）
    // .id 条件ID
    // .vl 该条件要求的返回值
    // .comp 比较方法（详见EF_ACTION_SYS_AI_COMPARE）
    virtual void AddCondition(DWORD id, int vl, EF_ACTION_SYS_AI_COMPARE comp) = 0;
    // 设置执行频率（仅在eASAE_Run模式下有效）
    FINLINE void SetFreq(DWORD tmin, DWORD tmax)
    {
        freq_min_t = tmin, freq_max_t = tmax;
    }
};
typedef FVector< IFAICommand* > fv_as_ai_pcommand;


//----------------------------------------------------------------
// AI行为状态（根状态是无条件即进入）
//----------------------------------------------------------------
class IFAIState : public IFMemObject
{
public:
    ACHAR st_name[eCD_MaxName];         // 状态名
    bool bIsLeaveBySubState;            // 进本状态的子状态时，被视为离开本状态

    FINLINE IFAIState()
        :bIsLeaveBySubState(true)
    {
        FMemzero(st_name, sizeof(st_name));
    }

    // 添加条件（重复的条件自动抛弃）
    // .id 条件ID
    // .vl 该条件要求的返回值
    // .comp 比较方法（详见EF_ACTION_SYS_AI_COMPARE）
    virtual void AddCondition(DWORD id, int vl, EF_ACTION_SYS_AI_COMPARE comp) = 0;
    // 添加执行命令（可添加重复的相同的命令，离开模式的命令将在离开本状态时忽略命令的时间参数而立即执行）
    // .st 执行时机（详见EF_ACTION_SYS_AI_STATE）
    // .cmd 新创建的条件
    virtual void AddCommand(EF_ACTION_SYS_AI_EXECUTE st, IFAICommand* cmd) = 0;
    // 添加一条子状态
    virtual bool AddState(IFAIState* st) = 0;
};
typedef FVector< IFAIState* > fv_as_ai_pnode;


//----------------------------------------------------------------
// AI对象
//----------------------------------------------------------------
class IFAIObject : public IFMemObject
{
protected:
    FINLINE IFAIObject()
    {}

public:
    // 取得所在行为系统
    virtual IFActionSystem* GetAS() = 0;
    // 取得绑定的行为对象
    virtual IFActionObject* GetAO() = 0;
    // 加载AI文件
    virtual bool LoadAI(const ACHAR* file) = 0;
    // 设置AI的根状态数据（根状态是无条件进入的。切换状态树和删除对象时，将自动删除当前状态树）
    // .st 根部状态，注意会自动清掉根部的条件
    virtual bool SetRoot(IFAIState* st) = 0;
    // 获取AI的根状态数据
    virtual IFAIState* GetRoot() = 0;
    // AI的运行
    virtual void Run(DWORD nt) = 0;
    // 获取当前的工作状态
    virtual IFAIState* GetNowState() = 0;
};
typedef FVector< IFAIState* > fv_as_ai_pobject;


#pragma pack(pop)


//----------------------------------------------------------------
// 行为逻辑处理句柄仓库
//----------------------------------------------------------------
typedef FAutoClassFactory< IFActionHandle, DWORD > IFActionHandleFactoryType;
class IFActionHandleFactory : public IFActionHandleFactoryType
{
public:
    // 注册行为句柄
    template < typename _DeriveTy >
    void RegisterHandle()
    {
        _DeriveTy _t;
        IFActionHandleFactoryType::Register< _DeriveTy >(_t.nTypeID);
    }
    // 创建行为句柄
    virtual IFActionHandle* NewHandle(DWORD id)
    {
        return IFActionHandleFactoryType::NewClass(id);
    }
    // 删除行为句柄
    virtual void DelHandle(IFActionHandle* p)
    {
        IFActionHandleFactoryType::DelClass(p);
    }
};


//----------------------------------------------------------------
// 行为条件仓库
//----------------------------------------------------------------
typedef FAutoClassFactory< IFAICondition, DWORD > IFAIConditionFactoryType;
class IFAIConditionFactory : public IFAIConditionFactoryType
{
public:
    // 注册条件
    template < typename _DeriveTy >
    void RegisterHandle()
    {
        _DeriveTy _t;
        IFAIConditionFactoryType::Register< _DeriveTy >(_t.nTypeID);
    }
    // 创建条件
    virtual IFAICondition* NewHandle(DWORD id)
    {
        return IFAIConditionFactoryType::NewClass(id);
    }
    // 删除条件
    virtual void DelHandle(IFAICondition* p)
    {
        IFAIConditionFactoryType::DelClass(p);
    }
};


//----------------------------------------------------------------
// 行为系统
//----------------------------------------------------------------
class IFActionSystem : public IFMemObject
{
public:
    // 获取行为句柄仓库
    virtual IFActionHandleFactory* GetOF() = 0;
    // 获取条件仓库
    virtual IFAIConditionFactory* GetCF() = 0;
    // 对某个对象执行行为
    // .id 行为ID
    // .ao 目标行为对象
    // .ap 行为参数，如果填0则使用行为对象的默认行为参数构造参数
    // .ac 行为条件，如果填0则使用行为对象的默认行为条件构造参数
    virtual bool Execute(DWORD id, IFActionObject* ao, FActionParameter* ap = 0, FActionProperty* pt = 0) = 0;
    // 运行
    // .ao 目标行为对象
    // .nt 当前时间
    virtual bool Run(IFActionObject* ao, DWORD nt) = 0;
    // 强制提前结束当前的行为（如果是因为切换行为需要自动结束当前行为，不需要调用此函数）
    // .ao 目标行为对象
    virtual bool Terminate(IFActionObject* ao) = 0;
    // 挂起或者恢复指定行为栈中某个类型行为对象
    // .ao 目标行为对象
    // .key 堆栈key（ao->GetTopAction().key 可获取当前正在执行的行为KEY）
    // .id 要处理的行为ID
    // .suspend true挂起，false恢复
    // .exclusion true除输入ID以外全部处理，false，只处理输出ID
    virtual bool Pause(IFActionObject* ao, DWORD key, DWORD id, bool suspend, bool exclusion) = 0;
    // 清空对象的行为栈
    virtual void Clear(IFActionObject* ao) = 0;
};


// 创建新的行为系统处理逻辑
extern FAPI IFActionSystem* FNewActionSystem(FNEW_FUNC_API, IFActionHandleFactory* phf, IFAIConditionFactory* pcf);
// 创建行为对象
extern FAPI IFActionObject* FNewActionObject(FNEW_FUNC_API, IFActionNotify* an, IFActionSystem* as);
// 创建AI对象
extern FAPI IFAIObject* FNewAIObject(FNEW_FUNC_API, IFActionSystem* as, IFActionObject* ao);
// 创建AI状态
extern FAPI IFAIState* FNewAIState(FNEW_FUNC_API, ACHAR* name);
// 创建AI命令
extern FAPI IFAICommand* FNewAICommand(FNEW_FUNC_API, IFActionSystem* as, DWORD id, DWORD det = 0, FActionParameter* ap = 0, FActionProperty* pt = 0);
